﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using EnvDTE;
using System.IO;

namespace NeosSDI.VsExtension
{
    /// <summary>
    /// Interaction logic for WindowCreateScaffoldController.xaml
    /// </summary>
    public partial class WindowCreateScaffoldController : System.Windows.Window
    {
        public EnvDTE.DTE Dte { get; set; }

        public string Command
        {
            get
            {
                return textboxScaffoldingCommand.Text;
            }
        }

        public bool DefineService
        {
            get
            {
                return checkboxGenerateService.IsChecked.Value;
            }
        }

        public string ServiceName
        {
            get
            {
                return textboxServiceName.Text;
            }
        }

        public WindowCreateScaffoldController()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(WindowCreateScaffoldController_Loaded);
        }

        void WindowCreateScaffoldController_Loaded(object sender, RoutedEventArgs e)
        {
            FillComboModel();
            FillComboTemplate();
        }

        /// <summary>
        /// Fill combo with all template
        /// </summary>
        private void FillComboTemplate()
        {
            comboTemplate.Items.Add(new ComboBoxItem() { Content = "Please select a template" });

            var activeProject = GetActiveProject(Dte);
            FileInfo fi = new FileInfo(activeProject.FullName);
            string scaffoldersPath = System.IO.Path.Combine(fi.DirectoryName, "CodeTemplates", "Scaffolders");
            foreach (DirectoryInfo dir in new DirectoryInfo(scaffoldersPath).GetDirectories())
            {
                if (dir.Name.ToLower().Contains("controller"))
                {
                    comboTemplate.Items.Add(new ComboBoxItem() { Content = dir.Name, Tag = dir.Name });
                }
            }
            comboTemplate.SelectedIndex = 0;
        }

        /// <summary>
        /// Fill combo with all Web project models
        /// </summary>
        private void FillComboModel()
        {
            comboModel.Items.Add(new ComboBoxItem() { Content = "Please select a model" });
            var activeProject = GetActiveProject(Dte);
            FillProjectClass(comboModel, activeProject, activeProject.ProjectItems);
            comboModel.SelectedIndex = 0;
        }

        internal static Project GetActiveProject(DTE dte)
        {
            Project activeProject = null;

            Array activeSolutionProjects = dte.ActiveSolutionProjects as Array;
            if (activeSolutionProjects != null && activeSolutionProjects.Length > 0)
            {
                activeProject = activeSolutionProjects.GetValue(0) as Project;
            }

            return activeProject;
        }


        private void FillProjectClass(ComboBox combobox, Project project, ProjectItems prjItems)
        {
            try
            {
                foreach (ProjectItem item in prjItems)
                {
                    ExamineItem(project, item, combobox);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + Environment.NewLine + ex.StackTrace);
            }
        }

        // examine an item
        private void ExamineItem(Project project, ProjectItem item, ComboBox combobox)
        {
            if (item == null)
                return;
            if (item.ProjectItems != null)
            {
                foreach (ProjectItem itemChild in item.ProjectItems)
                {
                    ExamineItem(project, itemChild, combobox);
                }
            }
            FileCodeModel model = (FileCodeModel)item.FileCodeModel;
            if (model == null)
                return;
            if (model.CodeElements == null)
                return;
            foreach (CodeElement codeElement in model.CodeElements)
            {
                ExamineCodeElement(project, codeElement, 3, combobox);
            }
        }

        // recursively examine code elements
        private void ExamineCodeElement(Project project, CodeElement codeElement, int tabs, ComboBox combobox)
        {
            tabs++;
            try
            {
                if (codeElement.Kind == vsCMElement.vsCMElementClass)
                {
                    if (!codeElement.FullName.Contains(".App_") &&
                        !codeElement.FullName.ToLower().Contains("controller") &&
                        !codeElement.FullName.ToLower().Contains("t4mvc") &&
                        codeElement.FullName.ToLower() != "neosmvc" &&
                        !codeElement.FullName.ToLower().Contains("script") &&
                        !codeElement.FullName.ToLower().Contains("links") &&
                        !codeElement.FullName.ToLower().Contains("webconfig") &&
                        codeElement.FullName.Replace("."+codeElement.Name, "") != project.Name)
                    {
                        string txt = codeElement.Name + " (" + codeElement.FullName + ")";
                        string dtoName = CheckAttribute(codeElement);
                        bool found = false;
                        foreach (ComboBoxItem itemC in combobox.Items)
                        {
                            if (itemC.Content.ToString() == txt)
                            {
                                found = true;
                            }
                        }
                        if (!found)
                        {
                            string fullName = codeElement.FullName;
                            if (!string.IsNullOrEmpty(dtoName))
                            {
                                fullName += "|" + dtoName;
                            }
                            combobox.Items.Add(new ComboBoxItem() { Content = txt, Tag = fullName });
                        }
                    }
                }

                foreach (CodeElement childElement in codeElement.Children)
                {
                    ExamineCodeElement(project, childElement, tabs, combobox);
                }
            }
            catch
            {
            }
        }

        private string CheckAttribute(CodeElement codeElement)
        {
            string fileName = codeElement.ProjectItem.FileNames[0];
            string className = codeElement.Name;

            try
            {
                string line;
                System.IO.StreamReader file = new System.IO.StreamReader(fileName);
                List<string> lines = new List<string>();
                while ((line = file.ReadLine()) != null)
                {
                    line = line.Replace(":", " ").Replace(",", " ");
                    string[] arrayWord = line.Split(' ');
                    if (line.ToLower().Contains(" class ") && arrayWord.Contains(className))
                    {
                        for (int i = lines.Count - 1; i >= 0; i--)
                        {
                            if (lines[i].Contains("{"))
                                break;
                            if (lines[i].Contains("}"))
                                break;
                            if (lines[i].Contains("[MapDto"))
                            {
                                string _line = lines[i].Trim();
                                while (_line.Contains(" "))
                                {
                                    _line = _line.Replace(" ", "");
                                }
                                _line = _line.Replace("[MapDto(typeof(", "").Replace("))]", "");
                                return _line.Trim();
                            }
                        }
                    }
                    lines.Add(line);
                }
                file.Close();
            }
            catch (Exception ex)
            {
            }
            return null;
        }

        private void buttonCancel_Click(object sender, RoutedEventArgs e)
        {
            DialogResult = false;
            this.Close();
        }

        private void buttonOK_Click(object sender, RoutedEventArgs e)
        {
            DialogResult = true;
            this.Close();
        }

        private void comboTemplate_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ComputeScaffoldCommand();
        }

        private void comboModel_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ComputeScaffoldCommand();
        }

        private void textboxControllerName_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (textboxControllerName != null && textboxServiceName != null && textboxControllerName.Text.Contains("Controller"))
            {
                textboxServiceName.Text = textboxControllerName.Text.Replace("Controller", "Service");
            }
            ComputeScaffoldCommand();
        }

        private void textboxServiceName_TextChanged(object sender, TextChangedEventArgs e)
        {
            ComputeScaffoldCommand();
        }

        private void checkboxGenerateService_Click(object sender, RoutedEventArgs e)
        {
            panelService.Visibility = checkboxGenerateService.IsChecked.Value ? Visibility.Visible : System.Windows.Visibility.Hidden;
            ComputeScaffoldCommand();
        }

        private void checkboxGenerateViews_Click(object sender, RoutedEventArgs e)
        {
            ComputeScaffoldCommand();
        }

        private void ComputeScaffoldCommand()
        {
            if (comboTemplate != null && comboModel != null && comboTemplate.SelectedIndex > 0 && comboModel.SelectedIndex > 0)
            {
                string command = "Scaffold ";
                string templateName = (comboTemplate.SelectedItem as ComboBoxItem).Tag.ToString();
                string modelName = (comboModel.SelectedItem as ComboBoxItem).Tag.ToString();
                string dtoName = "";
                if (modelName.Contains("|"))
                {
                    dtoName = modelName.Split('|')[1];
                    modelName = modelName.Split('|')[0];
                }
                string controllerName = textboxControllerName.Text;
                string serviceName = textboxServiceName.Text;
                command += templateName + " ";
                command += controllerName + " ";
                command += "-Model " + modelName + " ";
                if (!string.IsNullOrEmpty(dtoName))
                {
                    command += "-Dto " + dtoName + " ";
                }
                if (checkboxGenerateService.IsChecked.Value)
                {
                    command += "-Service ";
                    if (!string.IsNullOrEmpty(serviceName))
                    {
                        command += "-ServiceName " + serviceName + " ";
                    }
                }
                if (checkboxGenerateViews.IsChecked.Value)
                {
                    command += "-Views ";
                }

                if (textboxScaffoldingCommand != null)
                {
                    textboxScaffoldingCommand.Text = command;
                }
            }
        }
    }
}
